package com.itetchologyandenglish.home.aop;

import com.itetchologyandenglish.home.config.Log;
import com.itetchologyandenglish.home.enetity.AuthUser;
import com.itetchologyandenglish.home.enetity.SysLog;
import com.itetchologyandenglish.home.service.SysLogDao;
import com.itetchologyandenglish.home.service.UserAthService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

@Component  ///注入
@Aspect  //拦截类
public class LogAspect {
    @Resource
    SysLogDao sysLogDao;
    //    Map<String,String> map=sysLogDao.getSys();
    @Resource
    private UserAthService userAthService;

    //纯正的动态代理  环切
    @Around("execution(* com.itetchologyandenglish.home.controller.Api.*.*(..))")
    public Object arroundMethod(ProceedingJoinPoint joinPoint) throws ClassNotFoundException {
        //执行方法
        System.out.println("拦住了");
        Object proceed = null;
        long beginTime = System.currentTimeMillis();
        try {
            proceed = joinPoint.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        long time = System.currentTimeMillis() - beginTime;
        // 保存日志
        System.out.println("-----------准备打印日志:方法前");
        saveLog(joinPoint, time);
        System.out.println("------------已经过了打印方法");
        return proceed;
    }

    private void saveLog(ProceedingJoinPoint joinPoint, long time) throws ClassNotFoundException {
        /**
         * 方法内我们直接获取信息然后针对方法判断写入日志
         *
         * */
//        //拿到目标执行类的名字
//        String targetName = joinPoint.getTarget().getClass().getName();
//        Class targetClass = Class.forName(targetName);
//        //根据类拿到所有方法
//        Method[] methods = targetClass.getMethods();
//        //目标执行的方法
//        String methodNames = joinPoint.getSignature().getName();
//        //遍历method，比较是否相等
//        //拿到所有的参数
//        Object[] params = joinPoint.getArgs();
//        //记录是谁执行什么方法
//        String message = map.get(methodName);
//        String targetName = joinPoint.getTarget().getClass().getName();
//        Class targetClass = Class.forName(targetName);
        // Method[] Methods = clazz.getMethods();
        //for (Method field : Methods) {
        //判断这个字段上是否有相应的注解信息（FruitName.class）
        // if (field.isAnnotationPresent(Log.class)) {
        // TestAnnotationString tjs = field.getAnnotation(Log.class);
        // System.out.println("注释"+field.getName()+"   " +tjs.name());
        //    }
        //}
        SysLog sysLog = new SysLog();
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = requestAttributes.getRequest().getSession(true);
        AuthUser user = (AuthUser) session.getAttribute("user");
        sysLog.setUsername(user.getUsername());
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        // 请求的方法名
        //1.拿到方法类名
        String className = joinPoint.getTarget().getClass().getName();
        //2.拿到方法名
        String methodName = signature.getName();
        //实例化对象
        Class targetClass = Class.forName(className);
        //拿到所有方法，之后判断是否有注解，没有注解就不写入数据库
        Method[] Methods = targetClass.getMethods();
        for (Method field : Methods) {
            //判断这个字段上是否有相应的注解信息（FruitName.class）
            if (field.isAnnotationPresent(Log.class)) {
                Log log = field.getAnnotation(Log.class);
                String value=log.value().split("-")[0];
                if (log != null) {
                    // 注解上的描述
                    sysLog.setOperation(log.value());
                    sysLog.setModule(value);
                }
            }
        }

        sysLog.setMethod(className + "." + methodName + "()");
        sysLog.setTime(time);
        // 请求的方法参数值
        Object[] args = joinPoint.getArgs();
        // 请求的方法参数名称
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        if (args != null && paramNames != null) {
            String params = "";
            for (int i = 0; i < args.length; i++) {
                params += "  " + paramNames[i] + ": " + args[i].toString();
            }
            if(params.equals("")){
                params="无参数";
            }
            sysLog.setParams(params);
        }
        sysLogDao.saveSysLog(sysLog);
    }

}
